const fs = require('fs');
const path = require('path');
const dayjs = require('dayjs');

class CsvStorage {
  constructor() {
    const dateStr = dayjs().format('YYYYMMDDHHmm');
    this.projectsFile = path.join(__dirname, `projects_${dateStr}.csv`);
    this.branchesFile = path.join(__dirname, `branches_${dateStr}.csv`);
    
    this.projectHeaders = [
      'id',
      'gitlab_id',
      'name',
      'name_with_namespace',
      'path',
      'path_with_namespace',
      'web_url',
      'ssh_url_to_repo',
      'http_url_to_repo',
      'created_at',
      'last_activity_at',
      'visibility',
      'default_branch'
    ];
    
    this.branchHeaders = [
      'id',
      'project_id',
      'name',
      'merged',
      'protected',
      'developers_can_push',
      'developers_can_merge',
      'can_push',
      'web_url',
      'commit_id',
      'commit_short_id',
      'commit_title',
      'commit_created_at',
      'commit_author_name',
      'commit_author_email'
    ];
  }

  escapeCsvField(field) {
    if (field === null || field === undefined) {
      return '';
    }
    const str = String(field);
    if (str.includes(',') || str.includes('"') || str.includes('\n') || str.includes('\r')) {
      return '"' + str.replace(/"/g, '""') + '"';
    }
    return str;
  }

  parseCsvLine(line) {
    const result = [];
    let current = '';
    let inQuotes = false;
    
    for (let i = 0; i < line.length; i++) {
      const char = line[i];
      const nextChar = line[i + 1];
      
      if (char === '"') {
        if (inQuotes && nextChar === '"') {
          current += '"';
          i++;
        } else {
          inQuotes = !inQuotes;
        }
      } else if (char === ',' && !inQuotes) {
        result.push(current);
        current = '';
      } else {
        current += char;
      }
    }
    result.push(current);
    
    return result;
  }

  readCsvFile(filePath) {
    if (!fs.existsSync(filePath)) {
      return [];
    }
    
    const content = fs.readFileSync(filePath, 'utf8');
    const lines = content.split('\n').filter(line => line.trim());
    
    if (lines.length === 0) {
      return [];
    }
    
    const headers = this.parseCsvLine(lines[0]);
    const rows = [];
    
    for (let i = 1; i < lines.length; i++) {
      const values = this.parseCsvLine(lines[i]);
      const row = {};
      headers.forEach((header, index) => {
        const value = values[index];
        if (value === 'true') {
          row[header] = true;
        } else if (value === 'false') {
          row[header] = false;
        } else if (value === '') {
          row[header] = null;
        } else {
          row[header] = value;
        }
      });
      rows.push(row);
    }
    
    return rows;
  }

  writeCsvFile(filePath, headers, rows) {
    const lines = [headers.join(',')];
    
    for (const row of rows) {
      const values = headers.map(header => this.escapeCsvField(row[header]));
      lines.push(values.join(','));
    }
    
    fs.writeFileSync(filePath, lines.join('\n'), 'utf8');
  }

  async initialize() {
    try {
      if (!fs.existsSync(this.projectsFile)) {
        this.writeCsvFile(this.projectsFile, this.projectHeaders, []);
      }
      if (!fs.existsSync(this.branchesFile)) {
        this.writeCsvFile(this.branchesFile, this.branchHeaders, []);
      }
      console.log('CSV 存储初始化成功');
    } catch (err) {
      console.error('CSV 存储初始化失败:', err);
      throw err;
    }
  }

  async clearFiles() {
    try {
      this.writeCsvFile(this.projectsFile, this.projectHeaders, []);
      this.writeCsvFile(this.branchesFile, this.branchHeaders, []);
      console.log('CSV 文件已清空');
    } catch (err) {
      console.error('清空 CSV 文件失败:', err);
      throw err;
    }
  }

  async saveProjects(projects, batchSize = 100) {
    if (projects.length === 0) return [];

    const allSavedIds = [];
    const totalBatches = Math.ceil(projects.length / batchSize);
    
    const existingProjects = this.readCsvFile(this.projectsFile);
    const projectMap = new Map();
    existingProjects.forEach(p => {
      projectMap.set(parseInt(p.gitlab_id), p);
    });
    
    let nextId = existingProjects.length > 0 
      ? Math.max(...existingProjects.map(p => parseInt(p.id))) + 1 
      : 1;
    
    for (let i = 0; i < projects.length; i += batchSize) {
      const batch = projects.slice(i, i + batchSize);
      const batchNumber = Math.floor(i / batchSize) + 1;
      
      console.log(`  正在处理批次 ${batchNumber}/${totalBatches} (${batch.length} 个项目)`);
      
      try {
        for (const project of batch) {
          const gitlabId = parseInt(project.gitlab_id);
          let id;
          
          if (projectMap.has(gitlabId)) {
            const existing = projectMap.get(gitlabId);
            id = parseInt(existing.id);
            
            existing.name = project.name;
            existing.name_with_namespace = project.name_with_namespace;
            existing.path = project.path;
            existing.path_with_namespace = project.path_with_namespace;
            existing.web_url = project.web_url;
            existing.ssh_url_to_repo = project.ssh_url_to_repo;
            existing.http_url_to_repo = project.http_url_to_repo;
            existing.created_at = project.created_at;
            existing.last_activity_at = project.last_activity_at;
            existing.visibility = project.visibility;
            existing.default_branch = project.default_branch;
          } else {
            id = nextId++;
            const newProject = {
              id: id,
              gitlab_id: gitlabId,
              name: project.name,
              name_with_namespace: project.name_with_namespace,
              path: project.path,
              path_with_namespace: project.path_with_namespace,
              web_url: project.web_url,
              ssh_url_to_repo: project.ssh_url_to_repo,
              http_url_to_repo: project.http_url_to_repo,
              created_at: project.created_at,
              last_activity_at: project.last_activity_at,
              visibility: project.visibility,
              default_branch: project.default_branch
            };
            projectMap.set(gitlabId, newProject);
          }
          
          allSavedIds.push({ 
            id: id, 
            gitlabId: gitlabId
          });
        }
        
        console.log(`  批次 ${batchNumber}/${totalBatches} 完成`);
      } catch (err) {
        console.error(`保存批次 ${batchNumber} 失败:`, err);
        throw err;
      }
    }
    
    const allProjects = Array.from(projectMap.values());
    this.writeCsvFile(this.projectsFile, this.projectHeaders, allProjects);
    
    console.log(`已保存 ${allSavedIds.length} 个项目`);
    return allSavedIds;
  }

  async saveBranches(branches, batchSize = 100) {
    if (branches.length === 0) return;

    const totalBatches = Math.ceil(branches.length / batchSize);
    let totalSaved = 0;
    
    const existingBranches = this.readCsvFile(this.branchesFile);
    const branchMap = new Map();
    existingBranches.forEach(b => {
      const key = `${b.project_id}_${b.name}`;
      branchMap.set(key, b);
    });
    
    let nextId = existingBranches.length > 0 
      ? Math.max(...existingBranches.map(b => parseInt(b.id))) + 1 
      : 1;
    
    for (let i = 0; i < branches.length; i += batchSize) {
      const batch = branches.slice(i, i + batchSize);
      const batchNumber = Math.floor(i / batchSize) + 1;
      
      console.log(`  正在处理批次 ${batchNumber}/${totalBatches} (${batch.length} 个分支)`);
      
      try {
        for (const branch of batch) {
          const key = `${branch.project_id}_${branch.name}`;
          
          if (branchMap.has(key)) {
            const existing = branchMap.get(key);
            existing.merged = branch.merged;
            existing.protected = branch.protected;
            existing.developers_can_push = branch.developers_can_push;
            existing.developers_can_merge = branch.developers_can_merge;
            existing.can_push = branch.can_push;
            existing.web_url = branch.web_url;
            existing.commit_id = branch.commit_id;
            existing.commit_short_id = branch.commit_short_id;
            existing.commit_title = branch.commit_title;
            existing.commit_created_at = branch.commit_created_at;
            existing.commit_author_name = branch.commit_author_name;
            existing.commit_author_email = branch.commit_author_email;
          } else {
            const newBranch = {
              id: nextId++,
              project_id: branch.project_id,
              name: branch.name,
              merged: branch.merged,
              protected: branch.protected,
              developers_can_push: branch.developers_can_push,
              developers_can_merge: branch.developers_can_merge,
              can_push: branch.can_push,
              web_url: branch.web_url,
              commit_id: branch.commit_id,
              commit_short_id: branch.commit_short_id,
              commit_title: branch.commit_title,
              commit_created_at: branch.commit_created_at,
              commit_author_name: branch.commit_author_name,
              commit_author_email: branch.commit_author_email
            };
            branchMap.set(key, newBranch);
          }
          totalSaved++;
        }
        
        console.log(`  批次 ${batchNumber}/${totalBatches} 完成`);
      } catch (err) {
        console.error(`保存批次 ${batchNumber} 失败:`, err);
        throw err;
      }
    }
    
    const allBranches = Array.from(branchMap.values());
    this.writeCsvFile(this.branchesFile, this.branchHeaders, allBranches);
    
    console.log(`已保存 ${totalSaved} 个分支`);
  }

  async close() {
  }
}

module.exports = new CsvStorage();

